package com.siyoumi.mybatispuls;

import com.siyoumi.component.XRedis;
import com.siyoumi.component.api.jj.JJ;
import com.siyoumi.component.api.jj.RobotType;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.config.SysConfig;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XStr;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.springframework.stereotype.Component;

import java.sql.Statement;
import java.time.Duration;
import java.time.LocalDateTime;

/**
 * SQL拦截器
 */
@Slf4j
@Component
@Intercepts({
        @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
        @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),
        @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})
})
public class SqlInterceptor
        implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        LocalDateTime b = XDate.now();

        Object proceed = invocation.proceed();

        //检查慢SQL
        try {
            Duration between = XDate.between(b, XDate.now());
            long ms = between.toMillis();
            log.debug("sql_exec_time:{}ms", ms);

            if (!SysConfig.getIns().isDev()) {
                //大于2秒，示为慢sql，发钉钉
                if (ms > 2000) {
                    String sql = XHttpContext.get("sql");
                    String redisKey = "slow_sql";
                    if (XRedis.getBean().setIfExists(redisKey, "1", 60)) {
                        //1分钟内，只发1次
                        String msg = XStr.concat("慢SQL\n\n", sql);
                        String url = XHttpContext.getUrl();
                        Thread threadSend = new Thread(() -> {
                            JJ.getIns(RobotType.ERROR).send(msg, url, true);
                        });
                        threadSend.start();
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            log.error(ex.getMessage());
        }

        return proceed;
    }
}
